/*
 * @Author: secrets123
 * @Date: 2022-07-21 10:53:28
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2023-06-25 18:18:37
 * @FilePath: \stm32g431_AllRings\applications\eeprom.c
 * @Description:
 *
 * Copyright (c) 2022 by secrets123 1097290967@qq.com, All Rights Reserved.
 */
#include <rtthread.h>
#include <board.h>
#include "rtdebug.h"
#include "eeprom.h"
#include "soft_iic.h"

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/
#define EEPROM_I2C_ADDR 0xA0
#define EEPROM_PAGE_SIZE 0X80
// #define EEPROM_IIC_ERROR_COUNT_MAX  20
/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
_EEPROM EEPROM;
// static uint8_t eeprom_iic_error_count = 0;
/* Private function prototypes -----------------------------------------------*/

void User_Error_EEPROM(void)
{
    ;
}
/**
 * @brief 软件IIC读取EEPROM一个字节数据
 * @param
 *  @arg reg：读取寄存器地址
 *  @arg buf：读取的数据存储内存地址
 * @retval 返回0成功，返回1失败
 */
uint8_t EE_IIC_ReadByteFromSlave(uint16_t reg, uint8_t *buf)
{
    EE_IIC_Start();
    EE_IIC_SendByte(EEPROM_I2C_ADDR); // 发送从机地址
    if (EE_IIC_WaitAck())             // 如果从机未应答则数据发送失败
    {
        //        if(eeprom_iic_error_count >= EEPROM_IIC_ERROR_COUNT_MAX){
        User_Error_EEPROM(); // EEPROM报错
        //        }else {
        //            eeprom_iic_error_count ++;
        //        }
        EE_IIC_Stop();
        return 1;
    }
    EE_IIC_SendByte(reg >> 8); // 发送寄存器地址
    EE_IIC_WaitAck();
    EE_IIC_SendByte(reg); // 发送寄存器地址
    EE_IIC_WaitAck();

    EE_IIC_Start();
    EE_IIC_SendByte(EEPROM_I2C_ADDR + 1); // 进入接收模式
    EE_IIC_WaitAck();
    *buf = EE_IIC_ReadByte(0);
    EE_IIC_Stop(); // 产生一个停止条件
    //    eeprom_iic_error_count = 0;
    return 0;
}

/**
 * @brief 软件IIC写入EEPROM一个字节数据
 * @param
 *  @arg reg：指定写入寄存器地址
 *  @arg data：写入的数据值
 * @retval 返回0成功，返回1失败
 */
uint8_t EE_EE_IIC_SendByteToSlave(uint16_t reg, uint8_t data)
{
    EE_IIC_Start();
    EE_IIC_SendByte(EEPROM_I2C_ADDR); // 发送从机地址
    if (EE_IIC_WaitAck())
    {
        //        if(eeprom_iic_error_count >= EEPROM_IIC_ERROR_COUNT_MAX){
        User_Error_EEPROM(); // EEPROM报错
        //        }else {
        //            eeprom_iic_error_count ++;
        //        }
        EE_IIC_Stop();
        return 1; // 从机地址写入失败
    }
    EE_IIC_SendByte(reg >> 8); // 发送寄存器地址
    EE_IIC_WaitAck();
    EE_IIC_SendByte(reg); // 发送寄存器地址
    EE_IIC_WaitAck();
    EE_IIC_SendByte(data);
    if (EE_IIC_WaitAck())
    {
        //        if(eeprom_iic_error_count >= EEPROM_IIC_ERROR_COUNT_MAX){
        User_Error_EEPROM(); // EEPROM报错
        //        }else {
        //            eeprom_iic_error_count ++;
        //        }
        EE_IIC_Stop();
        return 1; // 数据写入失败
    }
    EE_IIC_Stop(); // 产生一个停止条件
    //    eeprom_iic_error_count = 0;
    return 0;
}

/**
 * @brief   在EEPROM的一个写循环中可以写多个字节，但一次写入的字节数
 *          不能超过EEPROM页的大小.
 * @param
 *		@arg pBuffer:缓冲区指针
 *		@arg WriteAddr:写地址
 *	  @arg NumByteToWrite:写的字节数
 * @retval  无
 */
uint8_t I2C_EE_PageWrite(uint8_t *buf, uint16_t reg, uint16_t l)
{
    uint8_t i = 0;
    uint16_t page_addr = 0;
    uint8_t page_internal_addr = 0;
    uint16_t page_write_addr = 0;
    uint16_t page_write_number = 0;

    page_write_number = l;

    if (reg < EEPROM_PAGE_SIZE)
    {
        page_addr = 0;
        page_internal_addr = reg;
    }
    else
    {
        page_addr = (reg / EEPROM_PAGE_SIZE);
        page_internal_addr = reg % EEPROM_PAGE_SIZE;
    }

    page_write_addr = (page_addr << 7) + page_internal_addr;

    // page_write_addr = reg & 0XFDFF;

    EE_IIC_Start();
    EE_IIC_SendByte(EEPROM_I2C_ADDR); // 发送从机地址
    if (EE_IIC_WaitAck())
    {
        //        if(eeprom_iic_error_count >= EEPROM_IIC_ERROR_COUNT_MAX){
        User_Error_EEPROM(); // EEPROM报错
        //        }else {
        //            eeprom_iic_error_count ++;
        //        }
        EE_IIC_Stop();
        return 1; // 从机地址写入失败
    }
    EE_IIC_SendByte(page_write_addr >> 8); // 发送寄存器地址
    EE_IIC_WaitAck();
    EE_IIC_SendByte(page_write_addr); // 发送寄存器地址
    EE_IIC_WaitAck();
    for (i = 0; i < page_write_number; i++)
    {
        EE_IIC_SendByte(buf[i]);
        if (EE_IIC_WaitAck())
        {
            //            if(eeprom_iic_error_count >= EEPROM_IIC_ERROR_COUNT_MAX){
            User_Error_EEPROM(); // EEPROM报错
            //            }else {
            //                eeprom_iic_error_count ++;
            //            }
            EE_IIC_Stop();
            return 1; // 数据写入失败
        }
    }

    EE_IIC_Stop(); // 产生一个停止条件
    //    eeprom_iic_error_count = 0;
    HAL_Delay(10);
    return 0;
}

/**
 * @brief   从EEPROM里面读取一块数据
 * @param
 *		@arg pBuffer:存放从EEPROM读取的数据的缓冲区指针
 *		@arg WriteAddr:接收数据的EEPROM的地址
 *	  @arg NumByteToWrite:要从EEPROM读取的字节数
 * @retval  无
 */
uint8_t I2C_EE_PageRead(uint8_t *buf, uint16_t reg, uint16_t l)
{
    uint16_t page_addr = 0;
    uint8_t page_internal_addr = 0;
    uint16_t page_write_addr = 0;
    uint16_t page_write_number = 0;

    page_write_number = l;

    if (reg < EEPROM_PAGE_SIZE)
    {
        page_addr = 0;
        page_internal_addr = reg;
    }
    else
    {
        page_addr = (reg / EEPROM_PAGE_SIZE);
        page_internal_addr = reg % EEPROM_PAGE_SIZE;
    }

    page_write_addr = (page_addr << 7) + page_internal_addr;

    // page_write_addr = reg & 0XFDFF;

    EE_IIC_Start();
    EE_IIC_SendByte(EEPROM_I2C_ADDR); // 发送从机地址
    if (EE_IIC_WaitAck())             // 如果从机未应答则数据发送失败
    {
        //        if(eeprom_iic_error_count >= EEPROM_IIC_ERROR_COUNT_MAX){
        User_Error_EEPROM(); // EEPROM报错
        //        }else {
        //            eeprom_iic_error_count ++;
        //        }
        EE_IIC_Stop();
        return 1;
    }
    EE_IIC_SendByte(page_write_addr >> 8); // 发送寄存器地址
    EE_IIC_WaitAck();
    EE_IIC_SendByte(page_write_addr); // 发送寄存器地址
    EE_IIC_WaitAck();

    EE_IIC_Start();
    EE_IIC_SendByte(EEPROM_I2C_ADDR + 1); // 进入接收模式
    EE_IIC_WaitAck();

    while (page_write_number)
    {
        if (page_write_number == 1)
            *buf = EE_IIC_ReadByte(0); // 读数据,发送nACK
        else
            *buf = EE_IIC_ReadByte(1); // 读数据,发送ACK
        page_write_number--;
        buf++;
    }

    EE_IIC_Stop(); // 产生一个停止条件
    //    eeprom_iic_error_count = 0;
    HAL_Delay(10);
    return 0;
}

////全片擦除函数，慎用
 void I2C_EE_Full_erase()
{
     uint16_t i;
     uint8_t test_buf[EEPROM_PAGE_SIZE];

     for(i = 0;i < EEPROM_PAGE_SIZE;i++){
       test_buf[i] = 0xFF;
     }

     for(i = 0; i < 512; i++){

         I2C_EE_PageWrite(test_buf, (i*EEPROM_PAGE_SIZE), EEPROM_PAGE_SIZE);\
        HAL_Delay(10);
     }

 }

// 随机写入函数，写入大小不超过页大小。可跨页写入。
uint8_t I2C_EE_RANDOM_Write(uint8_t *buf, uint16_t reg, uint16_t l)
{
    uint8_t i = 0;
    uint8_t write_flag = 0;
    uint8_t page_internal_addr = 0;

    page_internal_addr = reg % EEPROM_PAGESIZE;

    if (l > EEPROM_PAGESIZE)
        return 1;

    if ((EEPROM_PAGESIZE - page_internal_addr) >= l)
    {

        write_flag = I2C_EE_PageWrite(buf, reg, l);
    }
    else
    {

        i = EEPROM_PAGESIZE - page_internal_addr;

        write_flag = I2C_EE_PageWrite(buf, reg, i);

        HAL_Delay(5);

        write_flag = I2C_EE_PageWrite(buf + i, reg + i, (l - i));
    }

    return write_flag;
}
